package chap_05;

import chap_04.Dish;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * 映射
 */
public class Run_02 {

    /**
     * 流支持map方法，它会接受一个函数作为参数。这个函数会被应用到每个元素上，并将其映
     * 射成一个新的元素
     */
    @Test
    public void demo_01() {
        List<Dish> menu = Arrays.asList(
                new Dish("pork", false, 800, Dish.Type.MEAT),
                new Dish("beef", false, 700, Dish.Type.MEAT),
                new Dish("chicken", false, 400, Dish.Type.MEAT),
                new Dish("french fries", true, 530, Dish.Type.OTHER),
                new Dish("rice", true, 350, Dish.Type.OTHER),
                new Dish("season fruit", true, 120, Dish.Type.OTHER),
                new Dish("pizza", true, 550, Dish.Type.OTHER),
                new Dish("prawns", false, 300, Dish.Type.FISH),
                new Dish("salmon", false, 450, Dish.Type.FISH));

        List<String> dishNames = menu.stream()
                .map(Dish::getName)
                .collect(toList());
        System.out.println(dishNames);

        ArrayList<Dish> dishes = new ArrayList<>();

        while(dishes.size() < 20000) {
            dishes.addAll(menu);
        }

        // 找出每道菜的名称有多长
        long startTime = System.currentTimeMillis();
        dishes.parallelStream()
                .map(Dish::getName)
                .map(String::length)
                .collect(toList())
                .forEach(System.out::println);
        long endTime = System.currentTimeMillis();

        long startTime2 = System.currentTimeMillis();
        dishes.stream()
                .collect(toList())
                .forEach(item -> System.out.println(item.getName().length()));
        long endTime2 = System.currentTimeMillis();
        System.out.println("times:" + (endTime - startTime));
        System.out.println("times:" + (endTime2 - startTime2));
    }

    @Test
    public void demo_02() {
        List<String> words = Arrays.asList("Hello", "World");
        /*Stream<String[]> stream = words.stream()
                //将每个单词转换为由其字母构成的数组
                .map(word -> word.split(" "));*/

        List<String[]> collect = words.stream()
                .map(word -> word.split(" "))
                .distinct()
                .collect(toList());

                collect.forEach(System.out::println);
    }

    @Test
    public void demo_03() {
        List<String> words = Arrays.asList("Hello", "World");
        /*Stream<Stream<String>> streamStream = words.stream()
                //将每个单词转换为由其字母构成的数组
                .map(word -> word.split(" "))
                //让每个数组变成一个单独的流
                .map(Arrays::stream);*/

        words.stream()
                //将每个单词转换为由其字母构成的数组
                .map(word -> word.split(" "))
                //让每个数组变成一个单独的流
                .map(Arrays::stream)
                .distinct()
                .collect(toList())
                .forEach(System.out::println);
    }

    @Test
    public void demo_04() {
        List<String> words = Arrays.asList("Hello", "World");
        /*Stream<String> stringStream = words.stream()
                .map(w -> w.split(" "))
                //flatmap方法让你把一个流中的每个值都换成另一个流，然后把所有的流连接起来成为一个流。
                .flatMap(Arrays::stream);*/

        words.stream()
                .map(w -> w.split(" "))
                //flatmap方法让你把一个流中的每个值都换成另一个流，然后把所有的流连接起来成为一个流。
                .flatMap(Arrays::stream)
                .distinct()
                .collect(toList())
                .forEach(System.out::println);
    }

    @Test
    public void demo_08() {
        List<List<Object>> list = Arrays.asList(Arrays.asList(1,2,3), Arrays.asList("a", "b", "c"));
        //Stream<List> stream = list.stream();
        //Stream<Stream<Object>> streamStream = list.stream().map(List::stream);
        Stream<Object> stream = list.stream().flatMap(List::stream);
        stream.forEach(System.out::println);
    }

    /**
     * 映射
     */
    @Test
    public void demo_05() {
        List<Integer> numbers1 = Arrays.asList(1, 2, 3);
        List<Integer> numbers2 = Arrays.asList(3, 4);
        List<int[]> collect = numbers1.stream()
                .flatMap(i -> numbers2.stream()
                        .map(j -> new int[]{i, j})
                )
                .collect(toList());

        for (int[] ints : collect) {
            for (int anInt : ints) {
                System.out.print(anInt);
            }

            System.out.println();
        }
    }

    @Test
    public void demo_06() {
        List<Integer> numbers1 = Arrays.asList(1, 2, 3);
        List<Integer> numbers2 = Arrays.asList(3, 4);
        List<int[]> collect = numbers1.stream()
                .flatMap(i -> numbers2.stream()
                        .filter(j -> (i + j) % 3 == 0)
                        .map(j -> new int[]{i, j})
                )
                .collect(toList());

        for (int[] ints : collect) {
            for (int anInt : ints) {
                System.out.print(anInt);
            }

            System.out.println();
        }
    }
}
